<?php
/**
 * Class LogHandle(跟java一样定义四种日志类型)
 * @author shiroi
 */
class Log
{
    //文件名
    public $file = "log";

    //文件后缀
    public $file_suffix = ".log";

    //保存目录(默认根目录下)
    public $savePath = "D:/Desktop/log/";

    //操作的文件
    private $handler = null;

    //等级
    private $level = 15;

    private static $instance = null;

    private function __construct(){}

    private function __clone(){}

    /**
     * 初始化
     * @param string $savePath 保存目录(默认根目录下)
     * @param string $file 文件名
     * @param string $file_suffix 文件后缀
     * @param int $level
     * @return Log|null
     */
    public static function Init($savePath = "/",$file = "log", $file_suffix = ".log",$level = 15)
    {
        if(!self::$instance instanceof self)
        {
            self::$instance = new self();
            self::$instance->savePath = $savePath;
            self::$instance->file = $file;
            self::$instance->file_suffix = $file_suffix;
            self::$instance->__setHandle(new LogCycleHandler(
                self::$instance->savePath .
                DIRECTORY_SEPARATOR .
                self::$instance->file .
                self::$instance->file_suffix
            ));
            self::$instance->__setLevel($level);
        }
        return self::$instance;
    }

    /**
     * 设置操作文件
     * @param $handler
     */
    private function __setHandle($handler){
        $this->handler = $handler;
    }

    /**
     * 设置等级
     */
    private function __setLevel($level)
    {
        $this->level = $level;
    }

    /**
     * 记录debug日志
     * @param $msg
     */
    public static function DEBUG($msg)
    {
        self::$instance->write(1, $msg);
    }

    /**
     * 记录warn日志
     * @param $msg
     */
    public static function WARN($msg)
    {
        self::$instance->write(4, $msg);
    }

    /**
     * 记录error日志
     * @param $msg
     */
    public static function ERROR($msg)
    {
        $debugInfo = debug_backtrace();
        $stack = "[";
        foreach($debugInfo as $key => $val){
            if(array_key_exists("file", $val)){
                $stack .= ",file:" . $val["file"];
            }
            if(array_key_exists("line", $val)){
                $stack .= ",line:" . $val["line"];
            }
            if(array_key_exists("function", $val)){
                $stack .= ",function:" . $val["function"];
            }
        }
        $stack .= "]";
        self::$instance->write(8, $stack . $msg);
    }

    /**
     * 记录info日志
     * @param $msg
     */
    public static function INFO($msg)
    {
        self::$instance->write(2, $msg);
    }

    /**
     * 获取等级
     * @param int $level 等级
     */
    private function getLevelStr($level)
    {
        switch ($level)
        {
            case 1:
                return 'debug';
            case 2:
                return 'info';
            case 4:
                return 'warn';
            case 8:
                return 'error';
        }
    }

    /**
     * 写入日志
     * @param int $level 等级
     * @param string $msg 信息
     */
    protected function write($level,$msg)
    {
        if(($level & $this->level) == $level )
        {
            $msg = '['.date('Y-m-d H:i:s').']['.$this->getLevelStr($level).'] '.$msg."\n";
            $this->handler->write($msg);
        }
    }
}


/**
 * Class LogCycleHandler(日志的生命周期，实现内存释放)
 * @author shiroi
 */
class LogCycleHandler
{
    private $handle = null;

    public function __construct($file = '')
    {
        $this->handle = fopen($file,'a');
    }

    public function write($msg)
    {
        fwrite($this->handle, $msg, 4096);
    }

    public function __destruct()
    {
        fclose($this->handle);
    }
}


//example
//初始化日志系统(参数一：保存目录(默认根目录下)  参数二：文件名  参数三：文件后缀)
Log::Init('D:\Desktop\log');
Log::DEBUG("DEBUG");
Log::ERROR("ERROR");
Log::WARN("WARN");
Log::INFO("INFO");